#pragma once
#include "Mutex.hpp"
#include "Sem.hpp"
#include <vector>
static const int mycap = 6;
using namespace SemModule;
using namespace MutexModule;
template <class T>
class RingQueue {
    public:
        RingQueue(int cap = mycap)
        :_cap(mycap), _rq(cap), _space_sem(cap), _pindex(0), _data_sem(0), _cindex(0) {}
        void Equeue(const T& in) {
            // 申请信号量
            _space_sem.P();
            {
                LockGuard lockguard(_pmutex);
                // 生产
                _rq[_pindex++] = in;
                _pindex %= _cap;
            }
            _data_sem.V();
        }
        void Pop(T* out) {
            _data_sem.P();
            {
                LockGuard lockguard(_cmutex);
                // 消费
                *out = _rq[_cindex++];
                _cindex %= _cap;
            }
            _space_sem.V();
        }
    private:
        vector<T> _rq;
        int _cap;
        // 生产者
        Sem _space_sem;
        int _pindex;
        // 消费者
        Sem _data_sem;
        int _cindex;
        Mutex _cmutex; // 这里使用两个mutex来保证我们的并发，单个也是可以的（性能下降）
        Mutex _pmutex;    
};